package com.bjsxt.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TestLock {

    Lock lock = new ReentrantLock();

    public static void main(String[] args) {

        //1.可重入锁：Lock，ReentrantLock，synchronized锁
        //2.独占锁：synchronized锁，ReentrantLock，WriteLock
        //3.共享锁：ReadLock
        //4.公平锁和非公平锁

        //创建锁对象
        Lock lock = new ReentrantLock();        //默认非公平锁

        //获取锁的4种方式：

        //1.lock()，若获取不到则一直阻塞；获取到后才继续执行后续代码
        lock.lock();

        //2.tryLock()，若获取不到则立即返回false，不阻塞；若获取到则返回true，继续执行后续代码
        boolean flag2 = lock.tryLock();

        //3.tryLock(long time,TimeUnit unit)，指定时间内若获取到则继续执行后续代码，若未获取到则立即返回false，不阻塞
        try {
            boolean flag3 = lock.tryLock(100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //4.lockInterruptibly()，若获取不到则一直阻塞，若获取到则继续执行后续代码；若线程被中断，则抛出异常
        try {
            lock.lockInterruptibly();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //创建一个等待队列
        lock.newCondition();

        //释放锁
        lock.unlock();

        //读写锁
        ReadWriteLock rwLock = new ReentrantReadWriteLock();

        //返回的是同一把读锁
        Lock readLock1 = rwLock.readLock();
        Lock readLock2 = rwLock.readLock();

        //返回的是同一把写锁
        Lock writeLock1 = rwLock.writeLock();
        Lock writeLock2 = rwLock.writeLock();

        System.out.println(readLock1 == readLock2);
        System.out.println(writeLock1 == writeLock2);

    }

    public void method1() {
        lock.lock();        //1
        try {
            method2();
        } finally {
            lock.unlock();      //0
        }
    }

    public void method2() {
        lock.lock();        //2
        try {
            method3();
        }finally {
            lock.unlock();      //1
        }
    }

    public void method3() {
        lock.lock();        //3
        try {

        }finally {
            lock.unlock();      //2
        }
    }
}
